package com.dongnao.demo.database.db;

import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.text.TextUtils;

import com.dongnao.demo.database.annotation.DbFiled;
import com.dongnao.demo.database.annotation.DbTable;
import com.dongnao.demo.database.utils.DbUtils;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class BaseDao<T> implements IBaseDao<T> {

    private class Condition{
        private String whereCause;
        private String[] whereArgs;

        public Condition(Map<String, String> whereCause) {
            StringBuffer sql = new StringBuffer("1=1");
            List<String> whereList = new ArrayList<>();
            for(String columnName : whereCause.keySet()){
                if(TextUtils.isEmpty(columnName)) continue;
                String value = whereCause.get(columnName);
                if(TextUtils.isEmpty(value)) continue;
                sql.append(" and ").append(columnName).append("=?");
                whereList.add(value);
            }
            this.whereCause = sql.toString();
            this.whereArgs = whereList.toArray(new String[]{});
        }
        public Condition(ContentValues whereCause) {
            StringBuffer sql = new StringBuffer("1=1");
            List<String> whereList = new ArrayList<>();
            for(String columnName : whereCause.keySet()){
                if(TextUtils.isEmpty(columnName)) continue;
                String value = whereCause.getAsString(columnName);
                if(TextUtils.isEmpty(value)) continue;
                sql.append(" and ").append(columnName).append("=?");
                whereList.add(value);
            }
            this.whereCause = sql.toString();
            this.whereArgs = whereList.toArray(new String[]{});
        }
    }

    private static final String TAG = "BaseDao";

    private SQLiteDatabase sqLiteDatabase;

    private Class<T> entityClass;

    private String tableName;

    private Map<String, Field> cacheMap;

    private boolean isInit;


    protected boolean init(SQLiteDatabase sqLiteDatabase, Class<T> entityClass){
        try {
            this.sqLiteDatabase = sqLiteDatabase;
            this.entityClass = entityClass;
            if(!isInit){
                DbUtils.checkNull(sqLiteDatabase, entityClass);
                // 获取表名
                initTableName(entityClass);
                // 执行建表
                createTable(entityClass);
                initCacheMap();
                isInit = true;
            }
        }catch (Exception e){
            isInit = false;
        }
        return isInit;
    }

    private void initCacheMap() throws Exception{
        // 将数据库字段与javabean成员变量进行映射
        cacheMap = new HashMap<String, Field>();
        Cursor cursor = sqLiteDatabase.rawQuery("select * from " + tableName + " limit 1,0", null);
        String[] columnNames = cursor.getColumnNames();
        Field[] entityFileds = entityClass.getDeclaredFields();
        for(String columnName:columnNames){
            if(TextUtils.isEmpty(columnName)) continue;
            for(Field field:entityFileds){
                if(field == null) continue;
                field.setAccessible(true);
                String fieldName = field.getName();
                if(field.getAnnotation(DbFiled.class) != null){
                    fieldName = field.getAnnotation(DbFiled.class).value();
                }
                if(TextUtils.equals(columnName, fieldName)){
                    cacheMap.put(columnName, field);
                    break;
                }
            }
        }
        cursor.close();
    }

    private void createTable(Class<T> entityClass) throws Exception{
        String sql = DbUtils.genTabCreatorSql(tableName, entityClass);
        sqLiteDatabase.execSQL(sql);
    }

    private void initTableName(Class<T> entityClass) throws Exception{
        if(entityClass.getAnnotation(DbTable.class) == null){
            tableName = entityClass.getSimpleName();
        }else{
            tableName = entityClass.getAnnotation(DbTable.class).value();
        }
    }

    @Override
    public long insert(T entity) {
        ContentValues contentValues = DbUtils.genContentValues(cacheMap, entity);
        long insert = sqLiteDatabase.insert(tableName, null, contentValues);
        return insert;
    }

    @Override
    public int delete(T where) {
        Condition condition = new Condition(DbUtils.genContentValues(cacheMap, where));
        return sqLiteDatabase.delete(tableName, condition.whereCause, condition.whereArgs);
    }

    @Override
    public long update(T entity, T where) {
        ContentValues contentValues = DbUtils.genContentValues(cacheMap, entity);
        Condition condition = new Condition(DbUtils.genContentValues(cacheMap, where));
        return sqLiteDatabase.update(tableName, contentValues, condition.whereCause, condition.whereArgs);
    }

    @Override
    public List<T> queryAll() {
        String sql = "SELECT * FROM " + tableName;
        Cursor cursor = sqLiteDatabase.rawQuery(sql, null);
        return DbUtils.invokeObject(entityClass, cacheMap, cursor);
    }

    @Override
    public List<T> query(T where) {
        return null;
    }


}
